package com.lancoo.ccas53.aspect;


import cn.hutool.core.util.StrUtil;
import com.lancoo.ccas53.pojo.response.basicPlatform.UserInfo;
import com.lancoo.ccas53.service.YunBasicService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by Administrator on 2019-07-09.
 */
//@Component
//@Aspect
@Slf4j
@Order(2)
public class LogAspect {

    @Autowired
    private HttpServletRequest request;

    @Resource

    private YunBasicService yunBasicService;

    //参数列表 会将这些参数中的0转化为 null
    private List<String> paramList;

    public LogAspect() {
        this.paramList = Arrays.asList("courseId", "roomType", "gradeId", "subjectId", "campusId", "collegeId",
                "majorId", "courseType", "roomType", "roomId", "teacherId", "teachingClassId", "classId", "period", "beginWeek",
                "endWeek", "flag", "status", "keyWord");
    }

    /**
     * 切入点
     */
    @Pointcut("execution(* com.lancoo.ccas53.controller.*.*(..))")
    public void pc1() {
    }

    /**
     * @param joinPoint
     * @Description: 定义前置通知
     */
    @Before(value = "pc1()")
    public void before(JoinPoint joinPoint) {
        // 接收到请求，记录请求内容
        log.info("【注解：Before】------------------切面  before");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        log.info("【注解：Before】浏览器输入的网址=URL : " + request.getRequestURL().toString());
        log.info("【注解：Before】HTTP_METHOD : " + request.getMethod());
        log.info("【注解：Before】业务方法获得的参数=ARGS : " + Arrays.toString(joinPoint.getArgs()));
    }


    /**
     * @param jp
     * @Description: 后置最终通知, final增强，不管是抛出异常或者正常退出都会执行
     */
    @After(value = "pc1()")
    public void after(JoinPoint jp) {
        String name = jp.getSignature().getName();
        log.info(name + "方法执行结束");
    }


    /**
     * @param ret
     * @throws Throwable
     * @Description: 后置返回通知
     */
    @AfterReturning(returning = "ret", pointcut = "pc1()")
    public void afterReturning(JoinPoint jp, Object ret) throws Throwable {
        String name = jp.getSignature().getName();
        // 处理完请求，返回内容
        log.info(name + "方法的返回值 : " + ret);
    }

//    @AfterReturning("@annotation(com.lancoo.ccas53.aspect.LogAnnotation)")
    public void afterReturning(JoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Parameter[] parameters = method.getParameters();
        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
        Object[] args = point.getArgs();

        // 从请求头中获取参数
        String taskId = request.getHeader("taskId");
        if (StrUtil.isEmpty(taskId)) {
            return;
        }
        String userId = request.getHeader("userId");
        String username = request.getHeader("userName");
        String schoolId = request.getHeader("schoolId");
        UserInfo userInfo = yunBasicService.getUserInfo(userId);
        if (userInfo != null) {
            username = userInfo.getUserName();
        }

        // 获取注解参数
        String operationTerminal = logAnnotation.operationTerminal();
        String operationType = logAnnotation.operationType();
        String operationContent = logAnnotation.operationContent();

//        String fileName = logAnnotation.fieldName();
//        String entityName = logAnnotation.entityName();
//        String operationObject = getOperationObject(args, parameters, entityName, fileName);

//        if (StrUtil.isBlank(operationContent)) {
//            yunBasicService.uploadLog(schoolId, userId, username, operationTerminal, operationType, StrUtil.format("{}{}", GlobalConstant.operationTypeMap.get(operationType), operationObject, operationContent),taskId);
//        }
//        // 调用自定义方法进行处理
//        yunBasicService.uploadLog(schoolId, userId, username, operationTerminal, operationType, StrUtil.format("{}【{}】{}", GlobalConstant.operationTypeMap.get(operationType), operationObject, operationContent),taskId);


        if ("3".equals(operationType)) {
            return;
        }
        // 调用自定义方法进行处理
        yunBasicService.uploadLog(schoolId, userId, username, operationTerminal, operationType,
                operationContent, taskId);

    }

    public String getOperationObject(Object[] args, Parameter[] parameters, String entityName, String fileName) throws Throwable {
        List<String> parameterValueList = new ArrayList<>();
        String parameterValue = "";
        String operationObject = "";

        if (entityName != null && !"".equals(entityName)) {
            for (int i = 0; i < args.length; i++) {
                String parameterName = parameters[i].getName();
                if (parameterName.equals(entityName)) {
                    if (args[i] instanceof List) {
                        //如果entityName为列表，则获取所有指定字段的值
                        List list = (List) args[i];
                        for (Object o : list) {
                            Field field = o.getClass().getDeclaredField(fileName);
                            field.setAccessible(true);
                            parameterValueList.add(field.get(o).toString());
                        }
                    } else {
                        Field field = args[i].getClass().getDeclaredField(fileName);
                        field.setAccessible(true);
                        parameterValue = field.get(args[i]).toString();
                    }
                    break;
                }
            }
        } else if (fileName != null && !"".equals(fileName)) {
            for (int i = 0; i < args.length; i++) {
                String parameterName = parameters[i].getName();
                if (parameterName.equals(fileName)) {
                    parameterValue = args[i].toString();
                    break;
                }
            }
        }
        switch (entityName + "-" + fileName) {
            //申请时间设置
            case "dealTimeInput-type":
                operationObject = "1".equals(parameterValue) ? "开课计划" :
                        "2".equals(parameterValue) ? "预选课程->开课单位处理时段" :
                                "3".equals(parameterValue) ? "教学任务" :
                                        "";
                break;
            default:
                operationObject = parameterValueList.size() > 0 ? parameterValueList.toString() : parameterValue;
                return operationObject;
        }
        return operationObject;
    }


//    /**
//     * @param jp
//     * @Description: 后置异常通知
//     * @Title: afterThrowing
//     * @author Charles
//     * @Date 2019-07-09
//     */
//    @AfterThrowing(value = "pc1()", throwing = "e")
//    public void afterThrowing(JoinPoint jp, Exception e) {
//        String name = jp.getSignature().getName();
//        log.info(name + "方法异常:" + e.getMessage());
//    }
//

//    /**
//     * @param pjp
//     * @return
//     * @Description: 环绕通知, 环绕增强，相当于MethodInterceptor
//     * @author Charles
//     * @Date 2018年9月10日 下午3:52:56
//     */
//    @Around("pc1()")
//    public Object around(ProceedingJoinPoint pjp) {
//        log.info("【注解：Around . 环绕前】方法环绕start.....");
//        try {
//            Object[] args = handleParam(pjp);
//            //如果不执行这句，会不执行切面的Before方法及controller的业务方法
//            Object o = pjp.proceed(args);
//            log.info("【注解：Around. 环绕后】方法环绕proceed，结果是 :" + o);
//            return o;
//        } catch (Throwable e) {
//            MethodSignature signature = (MethodSignature) pjp.getSignature();
//            //获取method对象
//            Method method = signature.getMethod();
//            //获取方法的返回值的类型
//            Class returnType = method.getReturnType();
//            if (returnType == ResponseObject.class) {
//                log.error("【注解：Around. 环绕后】方法环绕proceed,方法异常抛出：", e);
//                ResponseObject responseObject = new ResponseObject();
//                responseObject.setCode(999);
//                responseObject.setMessage("服务器处理数据异常，请检查输入");
//                responseObject.setData(e);
//                return responseObject;
//            } else {
//                return null;
//            }
//        }
//    }

    Object[] handleParam(ProceedingJoinPoint joinPoint) {
        Object[] paramValues = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
        for (int i = 0; i < paramNames.length; i++) {
            if (paramList.contains(paramNames[i])) {
                if (paramValues[i] instanceof String) {
                    if (!"keyWord".equals(paramNames[i])) {
                        if ("0".equals(String.valueOf(paramValues[i]))) {
                            paramValues[i] = null;
                        }
                    } else {
                        if ("\"\"".equals(String.valueOf(paramValues[i]))) {
                            paramValues[i] = null;
                        }
                    }
                }
                if (paramValues[i] instanceof Integer && paramValues[i].equals(0)) {
                    paramValues[i] = null;
                }
            }
        }
        return paramValues;
    }

}